﻿using CSuperSocket.SocketBase.Protocol;
using SuperSocket.ProtoBase;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using Newtonsoft.Json;

namespace WebSvrUpdaterCore.Models
{
    public class MsgPacket : BinaryRequestInfo, IPackageInfo
    {
        /// <summary>
        /// 用户ID
        /// </summary>
        public  string Uid { get; set; }

        /// <summary>
        /// 请求ID
        /// 服务端向客户端发送请求,客户端回应对请求,需要带上服务端请求ID
        /// </summary>
        public string ReqesutId { get; set; }

        /// <summary>
        /// body内容效验
        /// </summary>
        public string CheckSum { get; set; }

        
        public static MsgPacket CreateNewInstance(string uid,string key,string body,string requestId)
        {
            if (string.IsNullOrEmpty(requestId)) requestId = Guid.NewGuid().ToString();

            return new MsgPacket(uid,key, Encoding.UTF8.GetBytes(body),requestId);
        }

        public static MsgPacket CreateNewInstance(string uid, string key, object body,string requestId)
        {
            return CreateNewInstance(uid, key, JsonConvert.SerializeObject(body),requestId);
        }

        public MsgPacket(string uid,string key, byte[] body,string requestId) : base(key, body)
        {
            if(string.IsNullOrEmpty(uid))
            {
                throw new ArgumentNullException("uid不允许为空");
            }
            Uid = uid;
            ReqesutId = requestId;
            CheckSum = GetMd5Str(body);
        }

        /// <summary>
        /// 序列化对象为btye数组
        /// 注意已在头尾加入了!$开始结束符号,用于发送
        /// </summary>
        /// <returns></returns>
        public byte[] ToBytes()
        {
            var jsonStr = "!"+JsonConvert.SerializeObject(this)+"$";
            return Encoding.UTF8.GetBytes(jsonStr);
        }

        public string GetTextBody()
        {
            if (Body != null && Body.Length > 0)
            {
                return Encoding.UTF8.GetString(Body);
            }
            return string.Empty;
        }

        /// <summary>
        /// 反序列化byte数组到对象 
        /// 注意:需要自行处理掉byte数组中的!和$
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static MsgPacket Parser(byte[] data)
        {
            if(data == null && data.Length < 1)
            {
                return null;
            }
            var str = Encoding.UTF8.GetString(data);
            return JsonConvert.DeserializeObject<MsgPacket>(str);            
        }

        public T ConvertBody<T>() where T :class
        {
            if (!CheckSumBody())
            {
                throw new CheckSumException { ErrorMd5 = CheckSum};
            }
           var  jsonStr = Encoding.UTF8.GetString(Body);
            if (!string.IsNullOrEmpty(jsonStr))
            {
                return JsonConvert.DeserializeObject<T>(jsonStr);
            }
            return null;
        }

        private string GetMd5Str(byte[] data)
        {
            var md5 = MD5.Create().ComputeHash(data);
            return BitConverter.ToString(md5).Replace("-", "");
        }

        /// <summary>
        /// 校验包体md5值
        /// </summary>
        /// <returns></returns>
        private bool CheckSumBody()
        {
            var md5Str = GetMd5Str(Body);
            if (string.IsNullOrEmpty(CheckSum)) return true;
            return CheckSum.Equals(md5Str, StringComparison.OrdinalIgnoreCase);
        }

        [JsonIgnore]
        public bool IsVaild
        {
            get
            {
                return CheckSumBody();
            }
        }
    }
   
    public static class MsgTypes 
    {
        /// <summary>
        /// 断开连接
        /// </summary>
        public const string Bye = "bye";
        /// <summary>
        /// 心跳包
        /// </summary>
        public const string Ping = "Ping";
        /// <summary>
        /// 服务器回应
        /// </summary>
        public const string PingReply = "RPing";
        /// <summary>
        /// echo
        /// </summary>
        public const string Echo = "Echo";
        /// <summary>
        /// 查询时间
        /// </summary>
        public const string Time = "Time";
        /// <summary>
        /// 回应时间
        /// </summary>
        public const string TimeReply = "RTime";
        /// <summary>
        /// 查询站点信息
        /// </summary>
        public const string WebSiteInfo = "WebSiteInfo";
        /// <summary>
        /// 回应站点信息
        /// </summary>
        public const string WebSiteInfoReply = "RWebSiteInfo";
        /// <summary>
        /// 新增站点
        /// </summary>
        public const string WebSiteAdd = "RWebSiteAdd";
        /// <summary>
        /// 回应新增站点
        /// </summary>
        public const string WebSiteAddReply = "RWebSiteAddReply";
        /// <summary>
        /// 修改站点信息
        /// </summary>
        public const string WebSiteEdit = "WebSiteEdit";
        /// <summary>
        /// 回应修改站点信息
        /// </summary>
        public const string WebSiteEditReply = "RWebSiteEdit";
        /// <summary>
        /// 删除站点
        /// </summary>
        public const string WebSiteDelete = "WebSiteDelete";
        /// <summary>
        /// 回应删除站点
        /// </summary>
        public const string WebSiteDeleteReply = "RWebSiteDelete";
        /// <summary>
        /// 下载文件
        /// </summary>
        public const string DownLoad = "DownLoad";
        /// <summary>
        /// 回应下载文件
        /// </summary>
        public const string DownLoadReply = "RDownLoad";
        /// <summary>
        /// 上传文件
        /// </summary>
        public const string Upload = "Upload";
        public const string UploadReply = "RUpload";
        /// <summary>
        /// 检查更新
        /// </summary>
        public const string CheckUpdate = "CheckUpdate";
        public const string CheckUpdateReply = "RCheckUpdate";

        /// <summary>
        /// 检查站点名称
        /// </summary>
        public const string CheckSiteName = "CheckSiteName";
        public const string CheckSiteNameReply = "RCheckSiteName";

        /// <summary>
        /// 检查程序池名称
        /// </summary>
        public const string CheckPoolName = "CheckPoolName";
        public const string CheckPoolNameReply = "RCheckPoolName";

        /// <summary>
        /// 获取版本
        /// 说明: 需要指定一个assembly文件,该文件定义为一个站点主程序,用于获取Version信息
        /// </summary>
        public const string GetVersion = "GetVersion";
        public const string GetVersionReply = "RGetVersion";

        /// <summary>
        /// 查询程序池
        /// </summary>
        public const string AppPoolInfo = "AppPoolInfos";
        public const string AppPoolInfoReply = "RAppPoolInfos";

        /// <summary>
        /// 添加程序池
        /// </summary>
        public const string AppPoolAdd = "AppPoolAdd";
        public const string AppPoolAddReply = "RAppPoolAdd";

        /// <summary>
        /// 编辑程序池
        /// </summary>
        public const string AppPoolEdit = "AppPoolEdit";
        public const string AppPoolEditReply = "RAppPoolEdit";

        /// <summary>
        /// 删除程序池
        /// </summary>
        public const string AppPoolDelete = "AppPoolDelete";
        public const string AppPoolDeleteReply = "RAppPoolDelete";


        /// <summary>
        /// 修改站点状态
        /// </summary>
        public const string ChangeSiteState = "ChangeSiteState";
        public const string ChangeSiteStateReply = "RChangeSiteState";


        /// <summary>
        /// 修改程序池状态
        /// </summary>
        public const string ChangePoolState = "ChangePoolState";
        public const string ChangePoolStateReply = "RChangePoolState";


        public const string IISAdminRequest = "IISAdminRequest";
        public const string IISAdminRespone = "IISAdminRespone";
    }

}
